package org.ccay.override;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.List;

public class TplOverrideTransformer implements ClassFileTransformer {

	/**
	 * 配置文件路径
	 */
	public static final String OVERRIDE_CLASSES_CONFIG_PATH = "config/overrideClass.txt";

	public static List<String> overrideClasses = new ArrayList<String>();

	public TplOverrideTransformer() {
		BufferedReader br = null;
		String str;
		try {
			br = new BufferedReader(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream(OVERRIDE_CLASSES_CONFIG_PATH)));
			while ((str = br.readLine()) != null && str.trim().length() > 0) {
				overrideClasses.add(str);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (br != null) {
					br.close();
				}
			} catch (IOException e) {
				System.err.println("close buffer reader excepton, the detail to as for: " + e.getMessage());
			}
		}
	}

	public byte[] getClassBytes(InputStream inStream) {
		if(inStream == null){
			return null;
		}
		ByteArrayOutputStream outStream = null;
		try {
			outStream = new ByteArrayOutputStream();
			int value;
			while ((value = inStream.read()) != -1) {
				outStream.write(value);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				inStream.close();
				outStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return outStream.toByteArray();
	}

	public byte[] transform(ClassLoader loader, String className, Class<?> c, ProtectionDomain pd, byte[] b) throws IllegalClassFormatException {
		String classInJar = pd.getCodeSource().getLocation().getPath();
		String location = classInJar.substring(classInJar.lastIndexOf("/")+1) + "!" + className.replace("/", ".");
		for (String oclassName : overrideClasses) {
			if (location.startsWith(oclassName)) {
				String filePath = className + ".clazz";
				InputStream inStream = this.getClass().getClassLoader().getResourceAsStream(filePath);
				if(inStream == null){
					System.err.println("Can find file " + filePath);
				}else{
					System.out.println("Overrided class define " + className + " by "+filePath);
					return getClassBytes(this.getClass().getClassLoader().getResourceAsStream(filePath));
				}
			}
		}
		return null;
	}
}